package net.siufung.simple.security.sevice.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.siufung.core.utils.StringPool;
import net.siufung.market.base.menu.mapper.entity.Permit;
import net.siufung.market.base.user.mapper.IUserMapper;
import net.siufung.market.base.user.mapper.entity.User;
import net.siufung.market.log.enums.LogTypes;
import net.siufung.market.log.mapper.entity.Log;
import net.siufung.market.log.service.ILogService;
import net.siufung.mybatis.properties.MybatisProperties;
import net.siufung.security.base.CurrentUser;
import net.siufung.security.base.CurrentUserGroup;
import net.siufung.security.base.enums.TokenGranters;
import net.siufung.security.base.exception.catetory.UsernameOrPasswordErrorException;
import net.siufung.security.base.service.ICurrentUserService;
import net.siufung.simple.security.sevice.ISecurityService;
import org.springframework.http.HttpMethod;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 陈建峰
 * @since 2022/5/6 5:12 下午
 */
@Slf4j
@Component("currentUserService")
@AllArgsConstructor
public class CurrentUserServiceImpl implements ICurrentUserService {

    private final MybatisProperties mybatisProperties;
    private final IUserMapper userMapper;
    private final ILogService logService;
    private final ISecurityService securityService;

    @Override
    public CurrentUser getUserByLoginName(String loginName, String tenantId) {
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getLoginName, loginName)
                .eq(mybatisProperties.getTenant().isEnable() && !Strings.isNullOrEmpty(tenantId),
                        User::getTenantId, tenantId));
        if(Objects.isNull(user)){
            throw new UsernameOrPasswordErrorException(String.format("用户不存在: '%s'.", loginName));
        } else {
            return this.create(user, Lists.newArrayList());
        }
    }

    private CurrentUser create(User user, Collection<? extends GrantedAuthority> authorities){
        Map<String, Object> extra = Maps.newHashMap();
        return new CurrentUser(
                user.getLoginName(),
                user.getLoginPwd(),
                !user.getDeleted(),
                true,
                true,
                true,
                authorities,
                String.valueOf(user.getId()),
                user.getUserName(),
                user.getMobile(),
                new CurrentUserGroup(String.valueOf(user.getDeptId()),
                        user.getTenantId()!=null?String.valueOf(user.getTenantId()): StringPool.EMPTY),
                user.getAdminState(),
                user.getInitFlag(),
                extra
        );
    }

    @Override
    public void updateLoginInfo(String loginName, TokenGranters tokenGranters, String parameters) {
        User userPo = userMapper.selectOne(new LambdaQueryWrapper<User>()
                        .eq(User::getLoginName, loginName));
        Log loggerDto = new Log();
        loggerDto.setUserName(userPo.getUserName());
        loggerDto.setUserId(Long.valueOf(userPo.getId()));
        loggerDto.setTitle(userPo.getUserName()+"登录系统");
        loggerDto.setType(LogTypes.LOGIN.getValue());
        loggerDto.setMethod(HttpMethod.POST.name());
        loggerDto.setParams(StrUtil.EMPTY);
        loggerDto.setRemoteIp(userPo.getLoginLastIp());
        loggerDto.setRequestUri("/oauth/token");
        loggerDto.setTenantId(Convert.toInt(userPo.getTenantId()));
        logService.save(loggerDto);
    }

    @Override
    public List<String> getAuthorities() {
        return securityService.getCurrentPermitList()
                .stream().map(Permit::getSign).collect(Collectors.toList());
    }
}
